package com.simpleplayer.MediaPlayer;

import androidx.annotation.IntDef;

import com.simpleplayer.services.LogUtil;
import com.simpleplayer.services.Timer;

import java.util.ArrayList;

/**
 * 设计该类的目的的是完成一些基础的服务，减少子类播放器的负担。
 * 该类目前负责两个工作：
 * 1. 状态的转换
 * 2. 进度的更新通知
 * 3. 显示模式的声明
 */
abstract class BasePlayer implements Timer.Ticker {

    private static final String TAG = "BasePlayer";

    @IntDef({IDLE, PREPARING, PREPARED, START, PLAYING, PAUSE, STOP, SEEKING, ERROR})
    public @interface PLAYBACKSTATE {}

    public static final int IDLE = 0;
    public static final int PREPARING = 1;
    public static final int PREPARED = 2;
    public static final int START = 3;
    public static final int PLAYING = 4;
    public static final int PAUSE = 5;
    public static final int STOP = 6;
    public static final int SEEKING = 7;
    public static final int ERROR = 8;

    public interface Listener {
        void onStateChanged(@PLAYBACKSTATE int oldState, @PLAYBACKSTATE int newState);
        void onTimeChanged(long timeMs);
        void onBufferingStart();
        void onBufferingEnd();
    }

    @PLAYBACKSTATE private int mCurrentState;
    protected ArrayList<Listener> mListeners;
    private final Timer mTimer;

    public BasePlayer() {
        mCurrentState = IDLE;
        mListeners = new ArrayList<>();
        mTimer = new Timer(this, 100);
    }

    public void addListener(Listener listener) {
        if (listener == null) {
            LogUtil.w(TAG, "add a null object to observe player state");
        }
        mListeners.add(listener);
    }

    public void removeListener(Listener listener) {
        mListeners.remove(listener);
    }

    protected void advanceStateTo(@PLAYBACKSTATE int newState) {
        int oldState = mCurrentState;
        mCurrentState = newState;

        LogUtil.i(TAG, "player " + this + " advance state from " + oldState + " to " + newState);

        if (oldState != mCurrentState) {
            for (Listener listener: mListeners) {
                listener.onStateChanged(oldState, mCurrentState);
            }
        }
    }

    @PLAYBACKSTATE
    public int getCurrentState() { return mCurrentState; }

    protected void prepare() {
        advanceStateTo(PREPARING);
    }

    protected void onPrepared() {
        advanceStateTo(PREPARED);
    }

    protected void start() {
        advanceStateTo(START);
    }

    protected void resume() {
        advanceStateTo(PLAYING);
        mTimer.start();
    }

    protected void pause() {
        advanceStateTo(PAUSE);
        mTimer.stop();
    }

    protected void seekTo(long position) {
        advanceStateTo(SEEKING);
    }

    protected void stop() {
        advanceStateTo(STOP);
        mTimer.stop();
    }

    protected void onError() {
        advanceStateTo(ERROR);
    }

    protected void notifyBufferingStart() {
        for (Listener listener: mListeners) {
            listener.onBufferingStart();
        }
    }

    protected void notifyBufferingEnd() {
        for (Listener listener: mListeners) {
            listener.onBufferingEnd();
        }
    }

    @Override
    public void onTick() {
        for (Listener listener: mListeners) {
            listener.onTimeChanged(getCurrentPosition());
        }
    }

    public boolean isPlaying() {
        return getCurrentState() == PLAYING;
    }

    protected abstract long getCurrentPosition();
    protected abstract long getDuration();
}
